#!/usr/bin/env python3
"""
数据库初始化脚本

该脚本负责创建数据库表结构和初始化必要的数据，包括：
- 创建所有数据表
- 初始化系统配置
- 创建默认角色和权限
- 初始化管理员账户
- 创建索引和约束
- 初始化基础数据
"""

import os
import sys
import logging
from datetime import datetime
from typing import List, Dict, Any
from pathlib import Path

# 添加项目根目录到路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from sqlalchemy import create_engine, text
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import sessionmaker

from src.data.models import Base, User, Role, UserRole, Permission, RolePermission, SystemConfig
from src.data.database import DatabaseManager, get_database_settings
from src.config.settings import get_settings
from src.utils.security import get_password_manager
from src.utils.exceptions import DatabaseError

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(),
        logging.FileHandler('init_db.log')
    ]
)
logger = logging.getLogger(__name__)


class DatabaseInitializer:
    """数据库初始化器"""
    
    def __init__(self):
        self.settings = get_settings()
        self.db_settings = get_database_settings()
        self.password_manager = get_password_manager()
        
        # 创建数据库管理器
        self.db_manager = DatabaseManager(
            database_url=self.db_settings.database_url,
            echo=self.settings.is_development()
        )
        
        # 创建会话工厂
        self.session_factory = sessionmaker(bind=self.db_manager.engine)
    
    def initialize_database(self):
        """初始化数据库"""
        try:
            logger.info("开始初始化数据库...")
            
            # 检查数据库连接
            self._check_database_connection()
            
            # 创建表结构
            self._create_tables()
            
            # 初始化系统配置
            self._initialize_system_configs()
            
            # 创建默认角色和权限
            self._create_default_roles_and_permissions()
            
            # 创建管理员账户
            self._create_admin_user()
            
            # 初始化基础数据
            self._initialize_base_data()
            
            logger.info("数据库初始化完成！")
            
        except Exception as e:
            logger.error(f"数据库初始化失败: {e}")
            raise DatabaseError(f"数据库初始化失败: {e}")
    
    def _check_database_connection(self):
        """检查数据库连接"""
        try:
            with self.db_manager.get_session() as session:
                session.execute(text("SELECT 1"))
            logger.info("数据库连接检查通过")
        except Exception as e:
            logger.error(f"数据库连接失败: {e}")
            raise DatabaseError(f"数据库连接失败: {e}")
    
    def _create_tables(self):
        """创建数据库表"""
        try:
            logger.info("开始创建数据库表...")
            
            # 创建所有表
            Base.metadata.create_all(bind=self.db_manager.engine)
            
            logger.info("数据库表创建完成")
            
        except SQLAlchemyError as e:
            logger.error(f"创建数据库表失败: {e}")
            raise DatabaseError(f"创建数据库表失败: {e}")
    
    def _initialize_system_configs(self):
        """初始化系统配置"""
        try:
            logger.info("开始初始化系统配置...")
            
            with self.db_manager.get_session() as session:
                # 检查是否已有配置
                existing_configs = session.query(SystemConfig).count()
                if existing_configs > 0:
                    logger.info("系统配置已存在，跳过初始化")
                    return
                
                # 默认系统配置
                default_configs = [
                    # 基础配置
                    {
                        'config_key': 'system.name',
                        'config_value': self.settings.app_name,
                        'config_type': 'string',
                        'config_description': '系统名称',
                        'config_group': 'system',
                        'is_system': True
                    },
                    {
                        'config_key': 'system.version',
                        'config_value': self.settings.app_version,
                        'config_type': 'string',
                        'config_description': '系统版本',
                        'config_group': 'system',
                        'is_system': True
                    },
                    {
                        'config_key': 'system.timezone',
                        'config_value': self.settings.timezone,
                        'config_type': 'string',
                        'config_description': '系统时区',
                        'config_group': 'system',
                        'is_system': True
                    },
                    
                    # 业务配置
                    {
                        'config_key': 'business.customer_code_prefix',
                        'config_value': self.settings.customer_code_prefix,
                        'config_type': 'string',
                        'config_description': '客户编号前缀',
                        'config_group': 'business',
                        'is_system': False
                    },
                    {
                        'config_key': 'business.customer_age_min',
                        'config_value': str(self.settings.customer_age_min),
                        'config_type': 'integer',
                        'config_description': '客户最小年龄',
                        'config_group': 'business',
                        'is_system': False
                    },
                    {
                        'config_key': 'business.customer_age_max',
                        'config_value': str(self.settings.customer_age_max),
                        'config_type': 'integer',
                        'config_description': '客户最大年龄',
                        'config_group': 'business',
                        'is_system': False
                    },
                    
                    # 安全配置
                    {
                        'config_key': 'security.password_min_length',
                        'config_value': str(self.settings.password_min_length),
                        'config_type': 'integer',
                        'config_description': '密码最小长度',
                        'config_group': 'security',
                        'is_system': True
                    },
                    {
                        'config_key': 'security.max_login_attempts',
                        'config_value': str(self.settings.max_login_attempts),
                        'config_type': 'integer',
                        'config_description': '最大登录尝试次数',
                        'config_group': 'security',
                        'is_system': True
                    },
                    {
                        'config_key': 'security.session_timeout',
                        'config_value': str(self.settings.session_timeout_minutes),
                        'config_type': 'integer',
                        'config_description': '会话超时时间（分钟）',
                        'config_group': 'security',
                        'is_system': True
                    },
                    
                    # 文件配置
                    {
                        'config_key': 'file.max_file_size',
                        'config_value': str(self.settings.max_file_size),
                        'config_type': 'integer',
                        'config_description': '最大文件大小（字节）',
                        'config_group': 'file',
                        'is_system': False
                    },
                    {
                        'config_key': 'file.allowed_extensions',
                        'config_value': ','.join(self.settings.allowed_file_extensions),
                        'config_type': 'string',
                        'config_description': '允许的文件扩展名',
                        'config_group': 'file',
                        'is_system': False
                    },
                    
                    # 通知配置
                    {
                        'config_key': 'notification.enable_email',
                        'config_value': 'true',
                        'config_type': 'boolean',
                        'config_description': '是否启用邮件通知',
                        'config_group': 'notification',
                        'is_system': False
                    },
                    {
                        'config_key': 'notification.enable_sms',
                        'config_value': 'true',
                        'config_type': 'boolean',
                        'config_description': '是否启用短信通知',
                        'config_group': 'notification',
                        'is_system': False
                    },
                    
                    # 备份配置
                    {
                        'config_key': 'backup.enable_auto_backup',
                        'config_value': str(self.settings.backup_enabled).lower(),
                        'config_type': 'boolean',
                        'config_description': '是否启用自动备份',
                        'config_group': 'backup',
                        'is_system': False
                    },
                    {
                        'config_key': 'backup.retention_days',
                        'config_value': str(self.settings.backup_retention_days),
                        'config_type': 'integer',
                        'config_description': '备份保留天数',
                        'config_group': 'backup',
                        'is_system': False
                    }
                ]
                
                # 创建配置记录
                for config_data in default_configs:
                    config = SystemConfig(**config_data)
                    session.add(config)
                
                session.commit()
                logger.info(f"已创建 {len(default_configs)} 个系统配置")
                
        except Exception as e:
            logger.error(f"初始化系统配置失败: {e}")
            raise DatabaseError(f"初始化系统配置失败: {e}")
    
    def _create_default_roles_and_permissions(self):
        """创建默认角色和权限"""
        try:
            logger.info("开始创建默认角色和权限...")
            
            with self.db_manager.get_session() as session:
                # 检查是否已有角色
                existing_roles = session.query(Role).count()
                if existing_roles > 0:
                    logger.info("角色已存在，跳过创建")
                    return
                
                # 创建默认权限
                permissions = self._create_default_permissions(session)
                
                # 创建默认角色
                roles = self._create_default_roles(session)
                
                # 分配权限给角色
                self._assign_permissions_to_roles(session, roles, permissions)
                
                session.commit()
                logger.info("默认角色和权限创建完成")
                
        except Exception as e:
            logger.error(f"创建默认角色和权限失败: {e}")
            raise DatabaseError(f"创建默认角色和权限失败: {e}")
    
    def _create_default_permissions(self, session) -> Dict[str, Permission]:
        """创建默认权限"""
        permissions_data = [
            # 客户管理权限
            ('customer.create', '客户档案创建', '客户档案管理', 'create'),
            ('customer.read', '客户档案查看', '客户档案管理', 'read'),
            ('customer.update', '客户档案更新', '客户档案管理', 'update'),
            ('customer.delete', '客户档案删除', '客户档案管理', 'delete'),
            ('customer.export', '客户档案导出', '客户档案管理', 'export'),
            ('customer.import', '客户档案导入', '客户档案管理', 'import'),
            
            # 活动管理权限
            ('activity.create', '活动创建', '邀约活动管理', 'create'),
            ('activity.read', '活动查看', '邀约活动管理', 'read'),
            ('activity.update', '活动更新', '邀约活动管理', 'update'),
            ('activity.delete', '活动删除', '邀约活动管理', 'delete'),
            ('activity.invite', '活动邀请', '邀约活动管理', 'invite'),
            ('activity.report', '活动报告', '邀约活动管理', 'report'),
            
            # 销售机会权限
            ('opportunity.create', '机会创建', '销售机会跟踪', 'create'),
            ('opportunity.read', '机会查看', '销售机会跟踪', 'read'),
            ('opportunity.update', '机会更新', '销售机会跟踪', 'update'),
            ('opportunity.delete', '机会删除', '销售机会跟踪', 'delete'),
            ('opportunity.assign', '机会分配', '销售机会跟踪', 'assign'),
            ('opportunity.followup', '机会跟进', '销售机会跟踪', 'followup'),
            
            # 产品管理权限
            ('product.create', '产品创建', '线路产品管理', 'create'),
            ('product.read', '产品查看', '线路产品管理', 'read'),
            ('product.update', '产品更新', '线路产品管理', 'update'),
            ('product.delete', '产品删除', '线路产品管理', 'delete'),
            ('product.price', '产品定价', '线路产品管理', 'price'),
            ('product.publish', '产品发布', '线路产品管理', 'publish'),
            
            # 出团管理权限
            ('tour.create', '出团创建', '出团管理', 'create'),
            ('tour.read', '出团查看', '出团管理', 'read'),
            ('tour.update', '出团更新', '出团管理', 'update'),
            ('tour.delete', '出团删除', '出团管理', 'delete'),
            ('tour.booking', '出团预订', '出团管理', 'booking'),
            ('tour.report', '出团报告', '出团管理', 'report'),
            
            # 客服管理权限
            ('service.create', '服务记录创建', '售后服务', 'create'),
            ('service.read', '服务记录查看', '售后服务', 'read'),
            ('service.update', '服务记录更新', '售后服务', 'update'),
            ('service.resolve', '服务问题解决', '售后服务', 'resolve'),
            ('service.survey', '满意度调查', '售后服务', 'survey'),
            
            # 数据统计权限
            ('statistics.read', '统计数据查看', '数据统计', 'read'),
            ('statistics.create', '统计报表创建', '数据统计', 'create'),
            ('statistics.export', '统计数据导出', '数据统计', 'export'),
            ('statistics.kpi', 'KPI指标管理', '数据统计', 'kpi'),
            
            # 客户分析权限
            ('analysis.read', '分析数据查看', '客户分析', 'read'),
            ('analysis.create', '分析报告创建', '客户分析', 'create'),
            ('analysis.segment', '客户分群', '客户分析', 'segment'),
            ('analysis.predict', '预测分析', '客户分析', 'predict'),
            
            # 系统管理权限
            ('system.user', '用户管理', '系统管理', 'manage'),
            ('system.role', '角色管理', '系统管理', 'manage'),
            ('system.permission', '权限管理', '系统管理', 'manage'),
            ('system.config', '系统配置', '系统管理', 'config'),
            ('system.backup', '数据备份', '系统管理', 'backup'),
            ('system.log', '系统日志', '系统管理', 'log'),
            ('system.monitor', '系统监控', '系统管理', 'monitor'),
        ]
        
        permissions = {}
        for code, name, module, action in permissions_data:
            permission = Permission(
                permission_code=code,
                permission_name=name,
                permission_description=f"{module} - {name}",
                module_name=module,
                action_type=action
            )
            session.add(permission)
            permissions[code] = permission
        
        return permissions
    
    def _create_default_roles(self, session) -> Dict[str, Role]:
        """创建默认角色"""
        roles_data = [
            ('admin', '系统管理员', '拥有系统所有权限', 1, True),
            ('business_admin', '业务管理员', '拥有业务管理权限', 2, True),
            ('sales_manager', '销售主管', '拥有销售管理权限', 3, True),
            ('sales_consultant', '销售顾问', '拥有销售执行权限', 4, True),
            ('marketing_staff', '市场专员', '拥有市场活动权限', 5, True),
            ('service_staff', '客服专员', '拥有客户服务权限', 6, True),
            ('finance_staff', '财务专员', '拥有财务相关权限', 7, True),
            ('data_analyst', '数据分析师', '拥有数据分析权限', 8, True),
        ]
        
        roles = {}
        for name, description, desc_full, level, is_system in roles_data:
            role = Role(
                role_name=name,
                role_description=desc_full,
                role_level=level,
                is_system=is_system
            )
            session.add(role)
            roles[name] = role
        
        return roles
    
    def _assign_permissions_to_roles(self, session, roles: Dict[str, Role], permissions: Dict[str, Permission]):
        """分配权限给角色"""
        # 角色权限映射
        role_permissions = {
            'admin': list(permissions.keys()),  # 管理员拥有所有权限
            'business_admin': [
                'customer.create', 'customer.read', 'customer.update', 'customer.export',
                'activity.create', 'activity.read', 'activity.update', 'activity.invite', 'activity.report',
                'opportunity.create', 'opportunity.read', 'opportunity.update', 'opportunity.assign',
                'product.create', 'product.read', 'product.update', 'product.price', 'product.publish',
                'tour.create', 'tour.read', 'tour.update', 'tour.booking', 'tour.report',
                'service.read', 'service.update', 'service.resolve',
                'statistics.read', 'statistics.create', 'statistics.export',
                'analysis.read', 'analysis.create', 'analysis.segment',
            ],
            'sales_manager': [
                'customer.create', 'customer.read', 'customer.update', 'customer.export',
                'activity.create', 'activity.read', 'activity.update', 'activity.invite', 'activity.report',
                'opportunity.create', 'opportunity.read', 'opportunity.update', 'opportunity.assign', 'opportunity.followup',
                'product.read', 'tour.read', 'tour.booking',
                'service.read', 'service.update',
                'statistics.read', 'statistics.create',
                'analysis.read', 'analysis.create',
            ],
            'sales_consultant': [
                'customer.create', 'customer.read', 'customer.update',
                'activity.read', 'activity.invite',
                'opportunity.create', 'opportunity.read', 'opportunity.update', 'opportunity.followup',
                'product.read', 'tour.read', 'tour.booking',
                'service.create', 'service.read', 'service.update',
                'statistics.read',
            ],
            'marketing_staff': [
                'customer.read', 'customer.export',
                'activity.create', 'activity.read', 'activity.update', 'activity.invite', 'activity.report',
                'product.read', 'tour.read',
                'statistics.read', 'statistics.create',
                'analysis.read', 'analysis.segment',
            ],
            'service_staff': [
                'customer.read', 'customer.update',
                'service.create', 'service.read', 'service.update', 'service.resolve', 'service.survey',
                'tour.read', 'tour.report',
                'statistics.read',
            ],
            'finance_staff': [
                'customer.read', 'tour.read', 'tour.booking',
                'statistics.read', 'statistics.create', 'statistics.export',
            ],
            'data_analyst': [
                'customer.read', 'customer.export',
                'activity.read', 'activity.report',
                'opportunity.read', 'product.read', 'tour.read', 'tour.report',
                'service.read', 'statistics.read', 'statistics.create', 'statistics.export', 'statistics.kpi',
                'analysis.read', 'analysis.create', 'analysis.segment', 'analysis.predict',
            ],
        }
        
        # 分配权限
        for role_name, permission_codes in role_permissions.items():
            role = roles[role_name]
            for permission_code in permission_codes:
                if permission_code in permissions:
                    permission = permissions[permission_code]
                    role_permission = RolePermission(
                        role_id=role.id,
                        permission_id=permission.id
                    )
                    session.add(role_permission)
    
    def _create_admin_user(self):
        """创建管理员账户"""
        try:
            logger.info("开始创建管理员账户...")
            
            with self.db_manager.get_session() as session:
                # 检查是否已有管理员
                existing_admin = session.query(User).filter_by(username='admin').first()
                if existing_admin:
                    logger.info("管理员账户已存在，跳过创建")
                    return
                
                # 创建管理员用户
                admin_password = "admin123"  # 默认密码，生产环境需要修改
                hashed_password = self.password_manager.hash_password(admin_password)
                
                admin_user = User(
                    username='admin',
                    real_name='系统管理员',
                    employee_id='EMP001',
                    department='信息技术部',
                    position='系统管理员',
                    phone='13800000000',
                    email='admin@crm.com',
                    password_hash=hashed_password,
                    password_updated_at=datetime.utcnow(),
                    join_date=datetime.utcnow(),
                    status='active'
                )
                session.add(admin_user)
                session.flush()  # 获取用户ID
                
                # 分配管理员角色
                admin_role = session.query(Role).filter_by(role_name='admin').first()
                if admin_role:
                    user_role = UserRole(
                        user_id=admin_user.id,
                        role_id=admin_role.id
                    )
                    session.add(user_role)
                
                session.commit()
                logger.info(f"管理员账户创建完成 - 用户名: admin, 密码: {admin_password}")
                
        except Exception as e:
            logger.error(f"创建管理员账户失败: {e}")
            raise DatabaseError(f"创建管理员账户失败: {e}")
    
    def _initialize_base_data(self):
        """初始化基础数据"""
        try:
            logger.info("开始初始化基础数据...")
            
            with self.db_manager.get_session() as session:
                # 这里可以初始化一些基础数据
                # 例如：常用的客户标签、产品分类、活动类型等
                
                # 示例：创建一些基础的客户标签
                from src.data.models import CustomerTag
                
                # 检查是否已有基础数据
                existing_tags = session.query(CustomerTag).filter_by(is_system=True).count()
                if existing_tags == 0:
                    # 创建系统标签（这里只是示例，实际应该创建标签定义表）
                    logger.info("基础数据已存在或不需要初始化")
                
                session.commit()
                logger.info("基础数据初始化完成")
                
        except Exception as e:
            logger.error(f"初始化基础数据失败: {e}")
            raise DatabaseError(f"初始化基础数据失败: {e}")
    
    def drop_all_tables(self):
        """删除所有表（谨慎使用）"""
        try:
            logger.warning("开始删除所有数据库表...")
            Base.metadata.drop_all(bind=self.db_manager.engine)
            logger.warning("所有数据库表已删除")
        except Exception as e:
            logger.error(f"删除数据库表失败: {e}")
            raise DatabaseError(f"删除数据库表失败: {e}")
    
    def reset_database(self):
        """重置数据库"""
        try:
            logger.warning("开始重置数据库...")
            self.drop_all_tables()
            self.initialize_database()
            logger.info("数据库重置完成")
        except Exception as e:
            logger.error(f"重置数据库失败: {e}")
            raise DatabaseError(f"重置数据库失败: {e}")


def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description='CRM数据库初始化工具')
    parser.add_argument('--reset', action='store_true', help='重置数据库（删除所有数据）')
    parser.add_argument('--drop', action='store_true', help='删除所有表')
    parser.add_argument('--init', action='store_true', default=True, help='初始化数据库')
    
    args = parser.parse_args()
    
    # 创建初始化器
    initializer = DatabaseInitializer()
    
    try:
        if args.reset:
            confirmation = input("确定要重置数据库吗？这将删除所有数据！(yes/no): ")
            if confirmation.lower() == 'yes':
                initializer.reset_database()
            else:
                print("操作已取消")
                return
        
        elif args.drop:
            confirmation = input("确定要删除所有表吗？这将删除所有数据！(yes/no): ")
            if confirmation.lower() == 'yes':
                initializer.drop_all_tables()
            else:
                print("操作已取消")
                return
        
        elif args.init:
            initializer.initialize_database()
        
        print("数据库操作完成！")
        
    except Exception as e:
        logger.error(f"数据库操作失败: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()